package com.angus.modules.front.controller;
import com.angus.api.front.domain.FrontUser;
import com.angus.api.front.domain.FrontSendCode;
import com.angus.api.front.model.FrontLoginUser;
import com.angus.common.core.domain.R;
import com.angus.common.core.enums.SendCodeScene;
import com.angus.common.core.utils.StringUtils;
import com.angus.common.core.utils.ip.IpUtils;
import com.angus.common.core.web.controller.BaseController;
import com.angus.common.core.web.domain.AjaxResult;
import com.angus.common.core.web.page.TableDataInfo;
import com.angus.common.redis.service.RedisService;
import com.angus.common.security.annotation.InnerAuth;
import com.angus.common.security.config.SendCodeConfig;
import com.angus.common.security.utils.SecurityUtils;
import com.angus.modules.front.service.IFrontSendCodeService;
import com.angus.modules.front.service.IFrontUserService;
import com.angus.modules.front.service.IFrontConfigService;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author lineCode
 */
@RestController
@RequestMapping("/front/user")
public class FrontUserController extends BaseController {

    @Resource
    private IFrontUserService frontUserService;

    @Resource
    private IFrontConfigService configService;

    @Resource
    private IFrontSendCodeService sendCodeService;

    @Resource
    private SendCodeConfig sendCodeConfig;

    @Resource
    private RedisService redisService;

    /**
     * 获取当前用户信息
     */
    @InnerAuth
    @GetMapping("/info/{username}")
    public R<FrontLoginUser> info(@PathVariable("username") String username) {
        FrontUser frontUser = frontUserService.selectUserByUserName(username);
        if (Objects.isNull(frontUser)) {
            return R.fail("用户名或密码错误");
        }
        FrontLoginUser sysUserVo = new FrontLoginUser();
        sysUserVo.setFrontUser(frontUser);
        return R.ok(sysUserVo);
    }

    @InnerAuth
    @PostMapping("/register")
    public R<Boolean> register(@RequestBody FrontUser frontUser) {
        String username = frontUser.getUserName();
        if (!("true".equals(configService.selectConfigByKey("front.account.registerUser"))))
        {
            return R.fail("当前系统没有开启注册功能！");
        }
        if (!frontUserService.checkUserNameUnique(frontUser))
        {
            return R.fail("保存用户'" + username + "'失败，注册账号已存在");
        }
        // 如果没有昵称，则动态生成昵称
        String nickName = frontUser.getNickName();
        if (StringUtils.isEmpty(nickName)){
            String newNickName = "SD_"+StringUtils.randomString(10);
            frontUser.setNickName(newNickName);
        }
        // 自动生成推荐码
        String recommendCode = redisService.getCacheObject("recommendCode");
        if (StringUtils.isEmpty(recommendCode)){
            recommendCode = StringUtils.buildRecommendCode(1);
        }else{
            recommendCode = StringUtils.buildRecommendCode(Integer.parseInt(recommendCode.substring(recommendCode.length() - 1)) + 1);
        }
        frontUser.setRecommendCode(recommendCode);
        redisService.setCacheObject("recommendCode", recommendCode);
        return R.ok(frontUserService.registerUser(frontUser));
    }

    /**
     *记录用户登录IP地址和登录时间
     */
    @InnerAuth
    @PutMapping("/recordLogin")
    public R<Boolean> recordLogin(@RequestBody FrontUser sysUser) {
        return R.ok(frontUserService.updateUserProfile(sysUser));
    }


    @InnerAuth
    @GetMapping("/selectUserByPhoneNum/{device}")
    public R<FrontLoginUser> selectUserByPhoneNum(@PathVariable("device") String device){
        FrontUser  frontUser = frontUserService.queryUserByPhoneNum(device);

        if (Objects.isNull(frontUser)) {
            return R.fail("用户不存在");
        }
        FrontLoginUser sysUserVo = new FrontLoginUser();
        sysUserVo.setFrontUser(frontUser);
        return R.ok(sysUserVo);
    }
    @InnerAuth
    @GetMapping("/selectUserByDevice/{device}/{type}")
    public R<FrontLoginUser> selectUserByDevice(@PathVariable("device") String device, @PathVariable("type") Integer type){
        FrontUser frontUser = frontUserService.queryUserByDevice(device, type);
        if (Objects.isNull(frontUser)) {
            return R.fail("用户不存在");
        }
        FrontLoginUser sysUserVo = new FrontLoginUser();
        sysUserVo.setFrontUser(frontUser);
        return R.ok(sysUserVo);
    }
    @InnerAuth
    @PostMapping("/saveSendCode")
    public R<Boolean> saveSendCode(@RequestBody FrontSendCode newSendCode){
        return R.ok(sendCodeService.saveSendCode(newSendCode));
    }

    @InnerAuth
    @PutMapping("/updateSendCode")
    public R<Boolean> updateSendCode(@RequestBody FrontSendCode newSendCode){
        return R.ok(sendCodeService.updateSendCode(newSendCode));
    }

    @GetMapping("/queryLastSendCode")
    public R<FrontSendCode> queryLastSendCode(
            @RequestParam(value = "device") String device,
            @RequestParam(value = "sceneCode", required = false) Integer sceneCode,
            @RequestParam(value = "dateTime", required = false) String dateTime
    ){
        // 参数校验
        if (StringUtils.isBlank(device)) {
            return R.fail("设备标识不能为空");
        }

        // 日期格式校验
        if (StringUtils.isNotBlank(dateTime) && !dateTime.matches("\\d{8}")) {
            return R.fail("日期格式不正确，应为yyyyMMdd格式");
        }
        return R.ok(sendCodeService.queryLastSendCode(device,sceneCode,dateTime));
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("info")
    public AjaxResult getInfo() {
        FrontUser user = frontUserService.queryUserById(SecurityUtils.getUserId());
        AjaxResult ajax = AjaxResult.success();
        ajax.put("data", user);
        return ajax;
    }

    /**
     * 更新用户信息
     */
    @PutMapping("/update")
    public R<Boolean> updateUser(@RequestBody FrontUser frontUser) {
        if (frontUser.getUserId() == null) {
            return R.fail("参数错误，请重试");
        }
        return R.ok(frontUserService.updateUserProfile(frontUser));
    }

    /**
     * 更新用户信息
     */
    @PutMapping("/update-bindinfo")
    public R<Boolean> updateBindInfo(@RequestBody Map<String, Object> requestData) {
        // 获取 JSON 中的字段
        Integer userIdInt = (Integer) requestData.get("userId");
        if (userIdInt == 0) {
            return R.fail("未登录，请重试");
        }

        Long userId = userIdInt.longValue();

        String phoneNumber = (String) requestData.get("phoneNumber");
        String userEmail = (String) requestData.get("userEmail");
        // 验证验证码
        String code = (String) requestData.get("code");
        Integer type = (Integer) requestData.get("type");
        Integer scene =  (Integer) requestData.get("scene");

        if (Objects.isNull(SendCodeScene.getCodeBySceneCode(scene))){
            return R.fail("验证码场景错误");
        }

        String device = StringUtils.isNotBlank(phoneNumber) ? phoneNumber : userEmail;
        if (StringUtils.isBlank(device)) {
            return R.fail("手机号或邮箱为空，请重试");
        }
        // 查询最后一次发送的验证码 (当天)
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
        LocalDateTime now = LocalDateTime.now();
        FrontSendCode lastSendCode = sendCodeService.queryLastSendCode(device, scene, now.toLocalDate().format(formatter));
        if (Objects.isNull(lastSendCode)) {
            return R.fail("验证码不存在");
        }

        LocalDateTime expireTime = lastSendCode.getCreateTime().plus(sendCodeConfig.getExpireTimes());
        if (now.isAfter(expireTime)) {
            return R.fail("验证码已过期");
        }

        if (!lastSendCode.getCode().equals(code)) {
            return R.fail("验证码错误");
        }
        if (lastSendCode.getUsed()) {
            return R.fail("验证码已使用");
        }
        if (Objects.isNull(SendCodeScene.getCodeBySceneCode(lastSendCode.getScene()))) {
            return R.fail("验证码场景错误");
        }
        if (!Objects.equals(lastSendCode.getType(), type)) {
            return R.fail("验证码类型错误");
        }
        if (lastSendCode.getSendStatus() != 1) {
            return R.fail("验证码发送失败");
        }
        // 更新验证码为已使用
        lastSendCode.setUsed(true);
        lastSendCode.setUseIp(IpUtils.getIpAddr());
        lastSendCode.setUseTime(Date.from(now.atZone(ZoneId.systemDefault()).toInstant()));
        sendCodeService.updateSendCode(lastSendCode);

        // 检查是否已经绑定过
        FrontUser frontUserInfo = frontUserService.queryUserByDevice(device, type);
        if (!Objects.isNull(frontUserInfo)) {
            return R.fail("该手机号或邮箱已绑定用户");
        }
        // 更新 class
        FrontUser frontUser = new FrontUser();
        frontUser.setUserId(userId);
        if (StringUtils.isNotBlank(phoneNumber)){
            frontUser.setPhoneNumber(phoneNumber);
        }else{
            frontUser.setUserEmail(userEmail);
        }
        // 更新用户信息
        return R.ok(frontUserService.updateUserProfile(frontUser));
    }

    /**
     * 获取用户全部信息
     */

    @GetMapping("/getUserList")
    public TableDataInfo getUserList(@RequestParam(required = false) String keyword, @RequestParam(required = false) Integer status) {
        startPage();
        List<FrontUser> list = frontUserService.queryAllUsers(keyword, status);
        return getDataTable(list);
    }

    /**
     * 批量删除用户
     */
    @DeleteMapping("/remove")
    public AjaxResult remove(@RequestBody List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return AjaxResult.warn("ID列表不能为空");
        }
        if (frontUserService.deleteUserByIds(ids)){
            return AjaxResult.success("删除成功");
        }
        return AjaxResult.error("删除失败");
    }

    @PutMapping("passwordRest")
    public AjaxResult passwordRest(@RequestBody FrontUser frontUser) {
        if (frontUserService.updateUserProfile(frontUser)){
            return AjaxResult.success("密码重置成功");
        }
        return AjaxResult.error("密码重置失败");
    }

    @PostMapping("findUserByEmail")
    public AjaxResult findUserByEmail(@RequestBody String email) {
        FrontUser frontUser = frontUserService.queryUserByEmail(email);
        if (Objects.isNull(frontUser)) {
            return AjaxResult.warn("用户不存在");
        }
        FrontLoginUser sysUserVo = new FrontLoginUser();
        sysUserVo.setFrontUser(frontUser);
        return AjaxResult.success(sysUserVo);
    }

    @GetMapping("/getUserStatistics")
    public AjaxResult  getUserStatistics(){
        return AjaxResult.success(frontUserService.getUserStatistics());
    }
}
